package com.yingyi.basic.service.impl;

import com.yingyi.basic.constant.RegisterMethod;
import com.yingyi.basic.exception.BusinessException;
import com.yingyi.basic.service.IVerifyCodeService;
import com.yingyi.basic.util.StrUtils;
import com.yingyi.basic.util.VerifyCodeUtils;
import com.yingyi.user.domain.User;
import com.yingyi.user.dto.BinderDto;
import com.yingyi.user.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.Map;
import java.util.concurrent.TimeUnit;

@Service
public class VerifyCodeServiceImpl implements IVerifyCodeService {

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private UserMapper userMapper;

    /**
     * 获取图形验证码 Base64格式的字符串形式
     * 思路：
     * 前提： 参数验证
     *  1 生成验证码
     *  2 存储验证码到redis中,并且设置过期时间 key value   key为前端传递的uuid value为生成的验证码
     *  3 生成图形验证码的Base64编码格式的字符串
     *
     * @param key
     * @return
     */
    @Override
    public String getVerifyCode(String key) throws BusinessException {
        if(StringUtils.isEmpty(key)){
            throw new BusinessException("参数不正确");
        }

        //get the verifyCode
        String code = StrUtils.getComplexRandomString(4);

        //save the verifyCode to redis
        redisTemplate.opsForValue().set(key, code, 3, TimeUnit.MINUTES);

        //generate the String with Base64 format for a image
        return VerifyCodeUtils.verifyCode(100, 40, code);
    }


    /**
     * 发送短信验证码
     * @param map
     */
    @Override
    public void sendSmsCode(Map<String, String> map) throws BusinessException {

        String phone = map.get("phone");
        String imageCode = map.get("imageCode");
        String imageCodeKey = map.get("imageCodeKey");
        //1 参数校验 非空校验、手机号是否已注册校验、 图形验证码校验(是否过期、有效)
        if(StringUtils.isEmpty(phone) ||
           StringUtils.isEmpty(imageCode) ||
           StringUtils.isEmpty(imageCodeKey)){

            throw new BusinessException("参数不正确，请确认后重新发送");
        }


        //phone
        User dbUser = userMapper.queryByPhone(phone);
        if(dbUser != null){
            throw new BusinessException("手机号已注册，请直接登录");
        }

        //imageCode
        Object imageCodeInRedis = redisTemplate.opsForValue().get(imageCodeKey);

        if(imageCodeInRedis == null){
            throw new BusinessException("图片验证码已失效，请重新获取");
        }

        if(!imageCode.equalsIgnoreCase(imageCodeInRedis.toString())){
            throw new BusinessException("图片验证码输入错误，请重新输入");
        }


        //调用方法生成验证码
        generateSmsCode(phone, RegisterMethod.PHONE_REGISTER);

        /*//2 获取验证码 key为 手机号+业务码 【一分钟以内不允许重复发送验证码、三分钟内使用同一个验证码】 在value中存入时间戳来进行判断
        //查询键 【phone+业务码】
        String key = phone.concat(RegisterMethod.PHONE_REGISTER);
        Object codeInRedis = redisTemplate.opsForValue().get(key);

        //存储验证码的值
        String code = null;
        if(codeInRedis == null){
        //2.1 如果不存在，则创建一个code
            code = StrUtils.getComplexRandomString(6);
        } else {
        //2.2 如果存在， 若验证码的时间是否小于一分钟，则不允许发送；
            code = codeInRedis.toString().split(":")[0];
            Long timeSaved = Long.valueOf(codeInRedis.toString().split(":")[1]);

            if(timeSaved + 1*60*1000 >= System.currentTimeMillis()){
                throw new BusinessException("请勿重复发送");
            }

        }

        // 将code存入 redis中 为了后续的判断验证码是否过了重发时间需要拼接一个时间戳
        redisTemplate.opsForValue().set(key, code + ":" + System.currentTimeMillis(), 3, TimeUnit.MINUTES);

        //3 发送短信验证码

        //SmsUtils.sendSms(phone, "你的验证码为：" + code + "，请在3分钟之内使用!");
        System.out.println("你的验证码为：" + code + "，请在3分钟之内使用!");*/
    }

    /**
     * 绑定微信时获取验证码
     * @param dto
     */
    @Override
    public void binderSmsCode(BinderDto dto) throws BusinessException {
        String phone = dto.getPhone();

        if(StringUtils.isEmpty(phone)) {
            throw new BusinessException("电话为空");
        }

        //调用方法获取验证码
        generateSmsCode(phone, RegisterMethod.WECHAT_REGISTER);

    }

    private void generateSmsCode(String phone, String businessCode) throws BusinessException {
        //获取验证码 key为 手机号+业务码 【一分钟以内不允许重复发送验证码、三分钟内使用同一个验证码】 在value中存入时间戳来进行判断
        //查询键 【phone+业务码】
        String key = phone.concat(businessCode);
        Object codeInRedis = redisTemplate.opsForValue().get(key);

        //存储验证码的值
        String code = null;
        if(codeInRedis == null){
            //2.1 如果不存在，则创建一个code
            code = StrUtils.getComplexRandomString(6);
        } else {
            //2.2 如果存在， 若验证码的发送时间间隔是否小于一分钟，是则不允许发送；
            code = codeInRedis.toString().split(":")[0];
            Long timeSaved = Long.valueOf(codeInRedis.toString().split(":")[1]);

            if(timeSaved + 1*60*1000 >= System.currentTimeMillis()){
                throw new BusinessException("请勿重复发送");
            }

        }

        // 将code存入 redis中 为了后续的判断验证码是否过了重发时间需要拼接一个时间戳
        redisTemplate.opsForValue().set(key, code + ":" + System.currentTimeMillis(), 3, TimeUnit.MINUTES);

        //3 发送短信验证码

        //SmsUtils.sendSms(phone, "你的验证码为：" + code + "，请在3分钟之内使用!");
        System.out.println("你的验证码为：" + code + "，请在3分钟之内使用!");
    }
}
